Dependency inversion

추상적 모듈이 구체적 모듈에 의존하는 게 전통적인 구조적 프로그래밍의 구조라면, 구체적 모듈이 추상적 모듈에 의존하는 식으로 의존성이 뒤집어진 설계를 의존성 역전이라고 부른다.

함수형 프로그래밍에서는 고차 함수, 객체지향프로그래밍에서는 다형성으로 의존성을 뒤집는다.

구조적 프로그래밍과의 차이점

구조적 프로그래밍에서는 시스템을 모듈화할 때 계층 간의 위계를 명확히 나누고 상위 계층이 하위 계층을 사용(즉 의존)하도록 만드는 게 중요한 설계 원칙이다. 여기에서 상위 계층이란 좀 더 추상적인(abstract) 계층을 말하고 하위 계층이란 좀 더 구체적인(concrete) 계층을 말한다.

첫째, 하위 계층의 서비스를 활용함으로써 시스템의 일부가 이득을 취했다(간결해졌다). 둘째 상위 계층을 들어내더라도 여전히 유용하고 사용 가능한 산출물(하위 계층 서비스들)이 남는다. … 만약 하위 계층의 모듈이 상위 계층의 모듈을 사용하게끔 설계를 했다면 올바른 위계를 얻어낼 수 없었을 것이고 시스템의 일부만 들어내기가 훨씬 더 어려웠을 것이며, 계층이라는 말 자체가 의미를 잃게 될 것이다. (First, parts of the system are benefited (simplified) because they use the services of lower levels. Second, we are able to cut off the upper levels and still have a usable and useful product. … If we had designed a system in which the “low level” modules made some use of the “high level” modules, we would not have the hierarchy, we would find it much harder to remove portions of the system, and “level” would not have much meaning in system)

—David Parnas, On the criteria to be used in decomposing systems into modules

이렇게 설계된 코드의 의존성 그래프를 그리면 모든 화살표가 위에서 아래로 향하는 형태가 된다. 의존성 역전이란 바로 이러한 의존관계를 뒤집는다는 의미로, 의존성 역전이 일어난 설계에서는 화살표 일부가 아래에서 위로 올라갑니다. UML에서는 속이 빈 삼각형 화살표(generalization 혹은 realization)로 표현한다.

이렇게 하면 하위 계층이 상위 계층에 의존하면서도 순환 참조(circular dependency)가 일어나지 않게 만들어서 이를 통해 원래 David Parnas가 강조하던 목적인 “시스템의 일부를 쉽게 들어낼 수 있도록 한다”를 여전히 달성할 수 있게 된다. (예: Observer pattern)

2024 © ak